#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

std::string comm_path = "./myfifo";

// int CreateNamedPipe(const std::string &comm_path)
// {
//     int res = mkfifo(comm_path.c_str(), 0666);
//     if (res != 0)
//     {
//         std::cerr << "mkfifo fail" << std::endl;
//     }
//     return res;
// }

// int RemoveNamePipe()
// {
//     int n = unlink(comm_path.c_str());
//     if (n != 0)
//     {
//         perror("unlink fail");
//     }
//     return n;
// }

// 写成宏可以降低耦合度
#define DefaultFd -1
// 身份
#define Creater 1 // 写的人创建
#define User 2
// 文件(命名管道)打开方式
#define Read O_RDONLY
#define Write O_WRONLY
// 缓冲区大小
#define BaseSize 4096

class NamedPipe
{
    bool OpenNamedPipe(int flags)
    {
        _fd = open(_fifo_path.c_str(), flags); // flags是打开方式
        if (_fd < 0)
        {
            perror("open fail");
            std::cerr << "open fail" << std::endl;
            return false;
        }
        else
        {
            std::cout << 1111 << std::endl;
            std::cout << _fifo_path << std::endl;
            std::cout << "_fd:" << _fd << " open success" << std::endl;
        }
        return true;
    }

public:
    // 1. 命名管道创建+删除
    NamedPipe(const std::string &path, int who)
        : _fifo_path(path), _id(who), _fd(DefaultFd)
    {
        if (_id == Creater)
        {
            int res = mkfifo(_fifo_path.c_str(), 0666); // res==result结果
            if (res != 0)                               // 创建成功返回0, 否则-1并设置errno(错误信息)
            {
                //perror("mkfifo fail");
                std::cerr << "mkfifo success" << std::endl;
            }
            else
            {
                std::cout << "mkfifo success" << std::endl;
            }
        }
    }
    ~NamedPipe()
    {
        std::cout << "~NamedPipe()" << std::endl;
        if (_fd != DefaultFd) // 关掉读/写端
            close(_fd);
        if (_id == Creater) // 谁创建的谁关闭
        {
            int n = unlink(_fifo_path.c_str());
            std::cout << "unlink namePipe" << std::endl;
            if (n != 0)
            {
                perror("unlink fail");
            }
        }
    }
    // 2. 以什么方式打开
    bool OpenForWrite()
    {
        return OpenNamedPipe(Write);
    }
    bool OpenForRead()
    {
        return OpenNamedPipe(Read);
    }
    // 3. 读写管道
    int WriteNamedPipe(const std::string &in) // in表示输入型参数
    {
        int n = write(_fd, in.c_str(), in.size());
        if (n < 0)
        {
            perror("write fail");
            std::cout << _fd << std::endl;
            return -1;
        }
        else
        {
            std::cout << "write success" << std::endl;
        }
        return n;
    }
    int ReadNamedPipe(std::string *out)
    {
        char buff[BaseSize];
        int n = read(_fd, buff, sizeof(buff));
        // if (n < 0)
        // {
        //     //perror("read fail");
        //     std::cerr << "read fail" << std::endl;
        //     std::cout << _fd << std::endl;
        //     return -1;
        // }
        *out = buff;
        return n;
    }

private:
    const std::string _fifo_path;
    int _id;
    int _fd;
};
